package com.googlecode.gwtbb.server.intermediate.picture;

import com.googlecode.gwtbb.client.shared.util.PictureUtils;
import com.googlecode.gwtbb.client.shared.util.StringUtils;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;

/**
 * @author Abraham Grief
 * @version $Id$
 * @since Dec 7, 2008
 */
public class Thumbnailer {
	private Watermarker watermarker;
	private int thumbWidth = 160;
	private int thumbHeight = 120;
	private double thumbAspectRatio = PictureUtils.getAspectRatio(thumbWidth, thumbHeight);
	private String thumbMark;

	public double getThumbAspectRatio() {
		return thumbAspectRatio;
	}

	public int getThumbHeight() {
		return thumbHeight;
	}

	public String getThumbMark() {
		return thumbMark;
	}

	public void setThumbMark(String thumbMark) {
		this.thumbMark = thumbMark;
	}

	public int getThumbWidth() {
		return thumbWidth;
	}

	public Watermarker getWatermarker() {
		return watermarker;
	}

	public void setWatermarker(Watermarker watermarker) {
		this.watermarker = watermarker;
	}

	/**
	 * based on http://blogs.cocoondev.org/mpo/archives/003584.html
	 * because standard way of making thumbnails in java is low-quality
	 * maybe we should use instead:
	 * http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
	 *
	 * @param imgFile the image file to be scaled
	 * @return true if the image was resized, false if a thumbnail the size of the orig was created
	 * @throws java.io.IOException if the thumbnail could not be created
	 */
	public boolean createThumbnail(File imgFile) throws IOException {
		boolean retVal;
		BufferedImage srcImage = ImageIO.read(imgFile);
		int dstWidth, dstHeight;
		int srcWidth = srcImage.getWidth(), srcHeight = srcImage.getHeight();
		double srcAspectRatio = PictureUtils.getAspectRatio(srcWidth, srcHeight);
		Image dstImage;
		// don't change size if it's smaller than needed... maybe we should make this configurable
		if (thumbWidth >= srcWidth && thumbHeight >= srcHeight) {
			dstWidth = srcWidth;
			dstHeight = srcHeight;
			dstImage = srcImage;
			retVal = false;
		} else {
			if (srcAspectRatio > thumbAspectRatio) {
				dstWidth = thumbWidth;
				dstHeight = (int)Math.round(thumbWidth / srcAspectRatio);
			} else if (srcAspectRatio < thumbAspectRatio) {
				dstWidth = (int)Math.round(thumbHeight * srcAspectRatio);
				dstHeight = thumbHeight;
			} else { // the aspect ratios are equal
				dstWidth = thumbWidth;
				dstHeight = thumbHeight;
			}
			dstImage = srcImage.getScaledInstance(dstWidth, dstHeight, Image.SCALE_SMOOTH);
			retVal = true;
		}
		// This code ensures that all the
		// pixels in the image are loaded.
		// .. i don't think we need this, so it has been removed.
		//Image temp = new ImageIcon(dstImage).getImage();
		Image temp = dstImage;

		// Create the buffered image.
		BufferedImage bufferedImage = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
		// Copy image to buffered image.
		Graphics g = bufferedImage.createGraphics();
		// Clear background and paint the image.
		g.setColor(Color.white);
		int tmpWidth = temp.getWidth(null);
		int tmpHeight = temp.getHeight(null);
		g.fillRect(0, 0, tmpWidth, tmpHeight);
		g.drawImage(temp, 0, 0, null);

		if (watermarker != null)
			watermarker.watermark(g, tmpWidth, tmpHeight);

		g.dispose();

		float softenFactor = 0.01f;
		float[] softenArray = {0, softenFactor, 0, softenFactor, 1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0};
		Kernel kernel = new Kernel(3, 3, softenArray);
		ConvolveOp convolveOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
		bufferedImage = convolveOp.filter(bufferedImage, null);

		String extension = StringUtils.getExtension(imgFile.getName());
		String format = extension.toUpperCase();

		String imgPath = imgFile.getPath();
		int fileNameIndex = imgPath.lastIndexOf(File.pathSeparatorChar);
		fileNameIndex = fileNameIndex < 0 ? 0 : fileNameIndex + 1;
		String dirPath = imgPath.substring(0, fileNameIndex);
		String picId = imgPath.substring(fileNameIndex, imgPath.indexOf("_", fileNameIndex));
		String thumbPath = PictureUtils.getPicFileName(dirPath + picId + thumbMark, bufferedImage.getWidth(), bufferedImage.getHeight(), extension);
		ImageIO.write(bufferedImage, format, new File(thumbPath));
		return retVal;
		/*
		BufferedImage dstImage = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = dstImage.createGraphics();
		AffineTransform scaleTransform = AffineTransform.getScaleInstance(((double)dstWidth)/srcWidth, ((double)dstHeight)/srcHeight);
		g.drawRenderedImage(srcImage, scaleTransform);
		ImageIO.write(dstImage, StringUtils.getExtension(imgFile.getName()).toUpperCase(), new File(getThumbPath(imgFile.getPath())));
*/
//		Image thumb = new Image();
//		thumb.setInput(imgFile);
//		float aspectRatio = getAspectRatio(thumb.getWidth(), thumb.getHeight());
//		if (aspectRatio >= thumbAspectRatio)
//			thumb.scaleToWidth(thumbWidth);
//		else
//			thumb.scaleToHeight(thumbHeight);
//		File thumbFile = new File(getThumbPath(imgFile.getPath()));
//		FileOutputStream fos = new FileOutputStream(thumbFile);
//		fos.write(thumb.getImage());
//		fos.close();
	}

	public void setThumbHeight(int thumbHeight) {
		this.thumbHeight = thumbHeight;
		thumbAspectRatio = PictureUtils.getAspectRatio(thumbWidth, thumbHeight);
	}

	public void setThumbWidth(int thumbWidth) {
		this.thumbWidth = thumbWidth;
		thumbAspectRatio = PictureUtils.getAspectRatio(thumbWidth, thumbHeight);
	}
}
